/*==============================================================================
**                                  STM32BOOT
**                      Proprietary - Copyright (C) 2014
**------------------------------------------------------------------------------
** Supported MCUs      : MCU STM32
** Supported Compilers : KeilC
**------------------------------------------------------------------------------
** File name         : Fls.c
**  
** Module name       : Flash Driver
**
** Summary: Flash Programming Functions adapted for 
**          ST Microelectronics STM32F10x Flash 
**
**= History ===================================================================
** 00.00.01  6/1/2014  Cuong Chu
** - Creation
==============================================================================*/
/******************************************************************************/
/* INCLUSIONS                                                                 */
/******************************************************************************/
#include "..\Fls.h"
/******************************************************************************/
/* DEFINITION OF TYPES                                                        */
/******************************************************************************/
typedef volatile unsigned char  vu8;
typedef volatile unsigned long  vu32;
typedef volatile unsigned short vu16;
/******************************************************************************/
/* DEFINITION OF MACROS                                                       */
/******************************************************************************/
#define M8(adr)  (*((vu8  *) (adr)))
#define M16(adr) (*((vu16 *) (adr)))
#define M32(adr) (*((vu32 *) (adr)))
/******************************************************************************/
/* DEFINITION OF CONSTANTS                                                    */
/******************************************************************************/
/* Peripheral Memory Map */
/* Flash */
#define FLASH_BASE      0x40022000
#define FLASH           ((FLASH_TypeDef*) FLASH_BASE)
/* FLASH BANK size */
#define BANK1_SIZE      0x00080000      /* Bank1 Size = 512kB */
/* Flash Registers */
typedef struct 
{
  vu32 ACR;                                     /* offset  0x000 */
  vu32 KEYR;                                    /* offset  0x004 */
  vu32 OPTKEYR;                                 /* offset  0x008 */
  vu32 SR;                                      /* offset  0x00C */
  vu32 CR;                                      /* offset  0x010 */
  vu32 AR;                                      /* offset  0x014 */
  vu32 RESERVED0[1];
  vu32 OBR;                                     /* offset  0x01C */
  vu32 WRPR;                                    /* offset  0x020 */
#ifdef STM32F10X_XL
  vu32 RESERVED1[8];
  vu32 KEYR2;                                   /* offset  0x044 */
  vu32 RESERVED2[1];
  vu32 SR2;                                     /* offset  0x04C */
  vu32 CR2;                                     /* offset  0x050 */
  vu32 AR2;                                     /* offset  0x054 */
#endif /* STM32F10X_XL */
} FLASH_TypeDef;
/* Flash Key */
#define RDPRT_KEY       0x5AA5
#define FLASH_KEY1      0x45670123
#define FLASH_KEY2      0xCDEF89AB
/* Flash Control Register definitions */
#define FLASH_PG        0x00000001
#define FLASH_PER       0x00000002
#define FLASH_MER       0x00000004
#define FLASH_OPTPG     0x00000010
#define FLASH_OPTER     0x00000020
#define FLASH_STRT      0x00000040
#define FLASH_LOCK      0x00000080
#define FLASH_OPTWRE    0x00000100
/* Flash Status Register definitions */
#define FLASH_BSY       0x00000001
#define FLASH_PGERR     0x00000004
#define FLASH_WRPRTERR  0x00000010
#define FLASH_EOP       0x00000020
/******************************************************************************/
/* DECLARATION OF INTERNAL VARIABLES                                          */
/* (Must use static for internal variables of module                          */
/******************************************************************************/
static uint32_t BaseAddress;
/******************************************************************************/
/* DEFINITION OF GLOBAL FUNCTIONS                                             */
/******************************************************************************/
/*******************************************************************************
** Function name: Fls_Unlock( uint32_t Address, uint32_t Clock, 
**                                 Fls_FunctionCodeType FunctionCode)
** Description  : The function called to unlock flash
** Parameter    : Address - Device Base Address
**                Clock   - Frequency of Clock System
**                FunctionCode - Select function for erase, program or verify
** Return value : None
** Remarks      : Called by IF_FLASH
*******************************************************************************/
void Fls_Unlock
( 
  uint32_t             Address, 
  uint32_t             Clock,
  Fls_FunctionCodeType FunctionCode
)
{
  /* Unlock Flash */
  FLASH->KEYR  = FLASH_KEY1;
  FLASH->KEYR  = FLASH_KEY2;
#ifdef STM32F10X_XL
  /* Flash bank 2 */
  FLASH->KEYR2 = FLASH_KEY1;                   
  FLASH->KEYR2 = FLASH_KEY2;
#endif /* STM32F10X_XL */
}
/*******************************************************************************
** Function name: Fls_Lock(Fls_FunctionCodeType FunctionCode)
** Description  : The function called for lock flash
** Parameter    : FunctionCode - Select function for erase, program or verify
** Return value : None
** Remarks      : Called by IF_FLASH
*******************************************************************************/
void Fls_Lock
(
  Fls_FunctionCodeType FunctionCode
)
{
  /* Lock Flash */
  FLASH->CR  |=  FLASH_LOCK;
#ifdef STM32F10X_XL
  /* Flash bank 2 */
  FLASH->CR2 |=  FLASH_LOCK;                  
#endif /* STM32F10X_XL */
}
/*******************************************************************************
** Function name: Fls_EraseSector(uint32_t Address)
** Description  : The function called for erase sector selected
** Parameter    : Address    - Sector Address
** Return value : FLS_OK     - if erase success
**                FLS_FAILED - if erase fail
** Remarks      : Called by IF_FLASH
*******************************************************************************/
Fls_ReturnType Fls_EraseSector
(
  uint32_t Address
)
{
#ifdef STM32F10X_XL
  /* Flash bank 2 */
  if (Address < (BaseAddress + BANK1_SIZE)) 
  {      
#endif /* STM32F10X_XL */
    /* Page Erase Enabled  */
    FLASH->CR  |=  FLASH_PER;                  
    /* Page Address */
    FLASH->AR   =  Address;         
    /* Start Erase */
    FLASH->CR  |=  FLASH_STRT;              
    /* wait erase */
    while (FLASH->SR  & FLASH_BSY) 
    {
      ;                  
    }
    /* Page Erase Disabled  */
    FLASH->CR  &= ~FLASH_PER;                   
#ifdef STM32F10X_XL
  }
  else 
  {                                        
    /* Flash bank 2 */
    FLASH->CR2 |=  FLASH_PER;
    FLASH->AR2  =  Address;
    FLASH->CR2 |=  FLASH_STRT;
    while (FLASH->SR2 & FLASH_BSY) 
    {
      ;
    }
    FLASH->CR2 &= ~FLASH_PER;
  }
#endif /* STM32F10X_XL */
  return FLS_OK;
}
/*******************************************************************************
** Function name: Fls_ProgramPage(uint32_t Address, uint32_t PageSize, 
**                                uint8_t* DataPtr)
** Description  : The function called for program data to on chip flash
** Parameter    : Address      - Page Start Address
**                ProgramSize  - Size of data program
**                DataPtr      - Point to Data write
** Return value: FLS_OK     - if program success
**               FLS_FAILED - if program fail
** Remarks: Called by IF_FLASH
*******************************************************************************/
Fls_ReturnType Fls_ProgramPage
(
  uint32_t Address, 
  uint32_t ProgramSize, 
  uint8_t  *DataPtr
)
{
  Fls_ReturnType ReturnValue = FLS_OK;
  /* Adjust size for Half Words */
  ProgramSize = (ProgramSize + 1) & ~1;                           
#ifdef STM32F10X_XL
  /* Flash bank 2 */
  if (Address < (BaseAddress + BANK1_SIZE)) 
  {       
#endif /* STM32F10X_XL */
    while (ProgramSize) 
    {
      /* Programming Enabled */
      FLASH->CR  |=  FLASH_PG;
      /* Program Half Word */
      M16(Address) = *((uint16_t *)DataPtr);
      while (FLASH->SR  & FLASH_BSY);
      /* Programming Disabled */
      FLASH->CR  &= ~FLASH_PG;
      /* Check for Errors */
      if (FLASH->SR  & (FLASH_PGERR | FLASH_WRPRTERR)) 
      {
        FLASH->SR  |= FLASH_PGERR | FLASH_WRPRTERR;
        ProgramSize = 0;
        ReturnValue = FLS_FAILED;
      } 
      else
      {
        /* Go to next Half Word */
        Address += 2;
        DataPtr += 2;
        ProgramSize -= 2;
      }
    }
#ifdef STM32F10X_XL
  }
  else 
  {
    /* Flash bank 2 */
    while (ProgramSize) 
    {
      FLASH->CR2 |=  FLASH_PG;
      M16(Address) = *((unsigned short *)DataPtr);
      while (FLASH->SR2 & FLASH_BSY);
      FLASH->CR2 &= ~FLASH_PG;
      /* Check for Errors */
      if (FLASH->SR2 & (FLASH_PGERR | FLASH_WRPRTERR)) 
      {
        FLASH->SR2 |= FLASH_PGERR | FLASH_WRPRTERR;
        ProgramSize = 0;
        ReturnValue = FLS_FAILED;
      }
      else
      {
        /* Go to next Half Word */
        Address += 2;
        DataPtr += 2;
        ProgramSize -= 2;
      }
    }
  }
#endif /* STM32F10X_XL */
  return ReturnValue;
}
/*******************************************************************************/
/*                      End of File                                            */
/*******************************************************************************/
